{\rtf1\ansi\ansicpg1252\uc1 \deff11\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f11\fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}MS Sans Serif;}{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}
{\f19\froman\fcharset161\fprq2 Times New Roman Greek;}{\f20\froman\fcharset162\fprq2 Times New Roman Tur;}{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}
{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;}{\f32\fmodern\fcharset162\fprq1 Courier New Tur;}{\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;
\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;
\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\widctlpar\adjustright \f11\fs20\cgrid \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar\adjustright \f2\fs20\cgrid \sbasedon0 \snext15 
Plain Text;}}{\*\listtable{\list\listtemplateid-205235596\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-390\li390\jclisttab\tx390 }{\listname 
;}\listid13312318}{\list\listtemplateid67698705\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid144905213}
{\list\listtemplateid67698705\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid345058181}{\list\listtemplateid67698703
\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid372506649}{\list\listtemplateid-205235596\listsimple
{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-390\li390\jclisttab\tx390 }{\listname ;}\listid549223625}{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0
\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid907230766}{\list\listtemplateid-205235596\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0
\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-390\li390\jclisttab\tx390 }{\listname ;}\listid1217081202}{\list\listtemplateid67698705\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1
\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1520200164}{\list\listtemplateid-205235596\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-390\li390\jclisttab\tx390 }{\listname ;}\listid1750930329}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1785465215}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid2033724308}{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid2076737053}}{\*\listoverridetable{\listoverride\listid1785465215\listoverridecount0\ls1}{\listoverride\listid144905213\listoverridecount0\ls2}
{\listoverride\listid2076737053\listoverridecount0\ls3}{\listoverride\listid2033724308\listoverridecount0\ls4}{\listoverride\listid345058181\listoverridecount0\ls5}{\listoverride\listid1520200164\listoverridecount0\ls6}{\listoverride\listid549223625
\listoverridecount0\ls7}{\listoverride\listid1217081202\listoverridecount0\ls8}{\listoverride\listid1750930329\listoverridecount0\ls9}{\listoverride\listid13312318\listoverridecount0\ls10}{\listoverride\listid907230766\listoverridecount0\ls11}
{\listoverride\listid907230766\listoverridecount0\ls12}}{\info{\title Exporting Biped Information from 3D Studio MAX}{\author yatesj}{\operator yatesj}{\creatim\yr1999\mo7\dy13\hr14\min18}{\revtim\yr1999\mo7\dy13\hr15\min23}
{\printim\yr1998\mo6\dy17\hr15\min2}{\version6}{\edmins18}{\nofpages5}{\nofwords1561}{\nofchars8902}{\*\company Autodesk, Inc.}{\nofcharsws0}{\vern89}}
\widowctrl\ftnbj\aendnotes\aftnstart0\hyphhotz0\aftnnar\lytprtmet\hyphcaps0\viewkind4\viewscale100\pgbrdrhead\pgbrdrfoot \fet0\sectd \linex0\endnhere\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2
\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6
\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}\pard\plain \qc\widctlpar\adjustright \f11\fs20\cgrid {\b\f0\fs36 Exporting 
\par Character Studio R2 Biped Information 
\par from 3D Studio MAX R2.X
\par }\pard \widctlpar\adjustright {\f0 
\par {\pntext\pard\plain\b\cgrid \hich\af0\dbch\af0\loch\f0 1.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24 Introduction
\par }\pard \qj\widctlpar\adjustright {\f0 
\par MAX exporters are not always written to handle Biped's non-uniform scaling of biped objects.  Furthermore, exporters are typically concerned with exporting only the node transformations in the hierarchy, rather than the biped default objects themselves.

\par }\pard \widctlpar\adjustright {\f0 
\par }\pard\plain \s15\widctlpar\adjustright \f2\fs20\cgrid {\f0 All bipeds created in Biped 2.0 or earlier store their scale in the transform matrix.  Biped uses non-uniform scaling, which could cause problems during export.  To eas
e this problem, we have provided two different ways to remove the non-uniform scaling.
\par }\pard\plain \widctlpar\adjustright \f11\fs20\cgrid {\f0 
\par {\pntext\pard\plain\fs20\cgrid \hich\af0\dbch\af0\loch\f0 1.\tab}}\pard \fi-390\li780\widctlpar\jclisttab\tx780{\*\pn \pnlvlbody\ilvl0\ls10\pnrnot0\pndec\pnstart1\pnindent390\pnhang{\pntxta .}}\ls10\adjustright {\f0 
A special  keyboard shortcut   operation "control-alt-e" for interactive control (for visual verification only)
\par }\pard \li390\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 
\par {\pntext\pard\plain\fs20\cgrid \hich\af0\dbch\af0\loch\f0 2.\tab}}\pard \fi-390\li780\widctlpar\jclisttab\tx780{\*\pn \pnlvlbody\ilvl0\ls10\pnrnot0\pndec\pnstart1\pnindent390\pnhang{\pntxta .}}\ls10\adjustright {\f0 
A BIPED SDK function call "BipIface->RemoveNonUniformScale(1)" that may be inserted into any existing MAX exporter. (see also bipexp.h, located in the cstudio\\docs folder)
\par }\pard \fi345\li720\widctlpar\adjustright {\f0 
\par }\pard \widctlpar\adjustright {\f0 Both are described below.  Section 4 describes some MAX SDK calls you can use to get general key-framing information from Biped. }{\f0\cgrid0 Section 6 tells how 
you can use the Biped export SDK to begin and end figure mode. }{\f0  We have also included a section }{\f0\cgrid0 7}{\f0 
 on how to remove non-Uniform Scaling for any MAX node (Biped or not) by using the more general MAX SDK function "decomp_affine". This more general technique, however, is not needed if either of the two above ways are used. 
\par 
\par {\pntext\pard\plain\b \hich\af0\dbch\af0\loch\f0 2.\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24\cgrid0 Changes to Biped Scale Storage

\par }\pard\plain \s15\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot1\pndec }\pnrnot1\adjustright \f2\fs20\cgrid {\f0\cgrid0 
It is important to note that Bipeds created using versions of Biped earlier than 2.1 store their scale in the transform matrix.  You can use the methods descr
ibed in this document to remove the non-uniform scale from such bipeds. Note that Bipeds created with }{\f0 Biped 2.1 or later store their scale in the object offset matrix.  }{\f0\cgrid0 
In theory, it is unnecessary to go through the non-uniform scale removal process for th
ese newer Bipeds. However, since during export there is no clear way to differentiate between these different versions of Bipeds, it is required that non-uniform scaling logic be active during export of all Bipeds, old or new.
\par }\pard \s15\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0\cgrid0 
\par }{\b\f0\ul\cgrid0 NOTE}{\f0\ul\cgrid0 : Removal of Non-uniform
 scaling will corrupt export of Physique assignments.  It is critical that the methods described below for removal of non-uniform scaling only be active during export of the Biped motion; they should be deactivated during Physique export.}{\f0\ul 
\par }{\f0  
\par }\pard \s15\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot1\pndec }\pnrnot1\adjustright {\f0\cgrid0 Please read the Character Studio realease notes for more information about this.
\par }\pard \s15\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 
\par }\pard\plain \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright \f11\fs20\cgrid {\f0 
\par {\pntext\pard\plain\b\cgrid \hich\af0\dbch\af0\loch\f0 3.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24 
Removing Non-Uniform Scaling using a keyboard shortcut
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 
\par As a visual test only, a special keyboard shortcut operation  "control-alt-e" has been added that will turn Biped's matrices into or
dinary MAX bones with no non-uniform scaling.  (Note: you will have to depress MAX's "Plug-in Keyboard Shortcut Toggle--the white button icon under the MAX viewport, and the Biped motion panel must be visible.)
\par      
\par When "control-alt-e" is hit, the biped 
objects will shrink to a uniform scaling of 1.0 in x, y, and z, but the matrix positions will remain the same. In effect, the Biped bones (seen by depressing the Biped "Bones" option in the Biped "Display" pull-down menu) and their Node transforms become 
i
dentical to MAX bones. The biped polygonal objects will shrink (and look funny) and the center-of-mass object will scale way up, but the biped bones will look the same. Only now the Biped's nodes contain no scaling information, just rotation and position.

\par 
\par }{\b\f0\ul Note}{\f0\ul : This method is meant only as a visual test and should not be employed during export of the Biped data.  Use of this feature a general method for export will corrupt Physique assigments.
\par }{\f0 
\par Instead, exporters should implement removal of non-uniform scale programmatically using the Biped SDK.  See below for functional access to this feature from Biped's SDK.
\par 
\par      
\par {\pntext\pard\plain\b\cgrid \hich\af0\dbch\af0\loch\f0 4.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24 
Using the MAX SDK to get keyframing information from Biped
\par }\pard \fi60\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0      
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 You can find the biped nodes if you know the names of the biped parts. You call the MAX Interface method:
\par      
\par }\pard \li720\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0  INode *GetINodeByName(const TCHAR *name)
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0      
\par Or you can just check the class of a node's controller.  The Biped class id's are included in bipexp.h.
\par      
\par To get the controller from an INode, call this MAX  INode method: 
\par 
\par }\pard \li720\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 Control *GetTMController().
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0      
\par To get the vertical, horizontal, and body rotation slave controllers from the body controller call this MAX animatable method:
\par      
\par }\pard \li720\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 Animatable *SubAnim(0) // vertical
\par Animatable *SubAnim(1) // horizontal
\par Animatable *SubAnim(2) // rotation
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0      
\par To get the key times from a controller or an animatable call one of  the following MAX animatable methods}{\f0\cgrid0 (the flags parameter in GetKeyTimes is ignored, since we do not have separate keys for position,rotation, and scale)}{\f0 :
\par      
\par }\pard \li720\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 BOOL GetNextKeyTime(TimeValue t,DWORD flags,TimeValue &nt) 
\par }{\f0\cgrid0 int GetKeyTimes(Tab<TimeValue> &times,Interval range,DWORD flags)}{\f0 
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0      
\par To get the matrix from an INode at a particular time call this MAX INode method:
\par      
\par }\pard \li720\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 Matrix3 GetNodeTM(TimeValue t, Interval* valid=NULL)
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0      
\par Biped uses non-uniform scaling, which could cause problems during  export. You should call a Biped exported method to set a flag to remove non-uniform scaling.  The function is called: 
\par 
\par }\pard \li720\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 RemoveNonUniformScale( integer FLAG)     
\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 
\par If FLAG is 1, NonUniform scaling is removed
\par If FLAG is 0,  NonUniform scaling is put back to its default
\par 
\par }\pard\plain \s15\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright \f2\fs20\cgrid {\b\f0\ul\cgrid0 NOTE}{\f0\ul\cgrid0 : Removal of Non-uniform scaling will corrupt export of Physique assignments.  It is }{\f0\ul\cgrid0 
critical that the NonUnform flag}{\f0\ul\cgrid0  be active only during export of the Biped motion; }{\f0\ul\cgrid0 it}{\f0\ul\cgrid0  should be deactivated during Physique export.}{\f0\ul 
\par }{ 
\par }\pard\plain \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright \f11\fs20\cgrid {\f0        
\par {\pntext\pard\plain\b\cgrid \hich\af0\dbch\af0\loch\f0 5.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24 Using the Biped Export Interface

\par }\pard \widctlpar\adjustright {\f0       
\par {\pntext\pard\plain\fs20\cgrid \hich\af0\dbch\af0\loch\f0 1.\tab}}\pard \fi-390\li780\widctlpar\jclisttab\tx780{\*\pn \pnlvlbody\ilvl0\ls8\pnrnot0\pndec\pnstart1\pnindent390\pnhang{\pntxta .}}\ls8\adjustright {\f0 
Find the Biped Controller you wish to export from (see sample code below or section }{\f0\cgrid0 3}{\f0  above).
\par }\pard \li390\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0 
\par {\pntext\pard\plain\fs20\cgrid \hich\af0\dbch\af0\loch\f0 2.\tab}}\pard \fi-390\li780\widctlpar\jclisttab\tx780{\*\pn \pnlvlbody\ilvl0\ls8\pnrnot0\pndec\pnstart1\pnindent390\pnhang{\pntxta .}}\ls8\adjustright {\f0 
Given a Biped controller c, get the Biped Export  Interface:
\par }\pard \widctlpar\adjustright {\f0               
\par IBipedExport *BipIface = (BipedExport*)c->GetInterface(I_BIPINTERFACE);         
\par      
\par At the moment this interface only allows you to remove the non-uniform scale}{\f0\cgrid0 , and to begin and end figure mode}{\f0 . In the future, more virtual functions will be added, and you'll be able to get more information abo
ut the biped via this interface.
\par      
\par Sample Code
\par      
\par      // Get a biped node - in this case the root
\par      INode *node = ip->GetINodeByName("Bip01");
\par      
\par      if (node)
\par      \{
\par          // Get the node's transform control
\par          Control *c = node->GetTMController();
\par      
\par          // You can test whether or not this is a biped controller with the following code:
\par          if ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
\par               (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) 
\par               (c->ClassID() == FOOTPRINT_CLASS_ID))
\par           \{
\par        
\par                 // Get the Biped Export Interface from the controller 
\par                 IBipedExport *BipIface = (IBipedExport *) c->GetInterface(I_BIPINTERFACE);
\par      
\par                 // Remove the non uniform scale
\par                 BipIface->RemoveNonUniformScale(1);
\par            
\par }\pard \nowidctlpar\adjustright {\f0\cgrid0                 // Redraw if you want to see the result
\par                 ip->RedrawViews(ip->GetTime());
\par 
\par                 // Release the interface when you are done with it
\par                 c->ReleaseInterface(I_BIPINTERFACE, BipIface);
\par            \}
\par     \}
\par      
\par      
\par {\pntext\pard\plain\b \hich\af0\dbch\af0\loch\f0 6.\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24\cgrid0 
Other Functions available in the Biped Export Interface
\par }\pard \nowidctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f0\cgrid0 
\par There are two other functions available from the Biped export interface.  Using them, you can begin or end figure mode.  They are:
\par \tab BeginFigureMode(int redraw);
\par \tab EndFigureMode(int redraw);
\par 
\par If redraw = 0, then the display is not updated in MAX
\par If redraw = 1, then the display is  updated in MAX}{\b\f0\fs24\cgrid0 
\par 
\par {\pntext\pard\plain\b \hich\af0\dbch\af0\loch\f0 7.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls12\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}\ls12\adjustright {\b\f0\fs24\cgrid0 General}{\b\f0\fs24 
 Notes on Removing Non-Uniform Scaling
\par }\pard \widctlpar\adjustright {\b\f0\fs24 
\par }{\f0 Note: This more general technique is not needed if the above Biped specific techniques are used.
\par 
\par      For each node in a MAX  node hierarchy: 
\par      \{
\par      current_matrix = node->GetNodeTM(t);
\par      parent_matrix =  parent_node->GetNodeTM(t);
\par      relative_matrix = cur_mat * Inverse( par_mat));
\par      Euler angles = Matrix_to_Euler(relative_matrix);
\par      \}
\par 
\par      //UNIFORM_MATRIX REMOVES 
\par      //NON-UNIFORM SCALING FROM MATRIX
\par      
\par      //must include this in your file's header
\par      #include "decomp.h" 
\par      
\par      Matrix3 Uniform_Matrix(Matrix3 orig_cur_mat)
\par      \{          
\par         AffineParts   parts;  
\par         Matrix3       mat;   
\par      
\par       ///Remove  scaling  from orig_cur_mat
\par       //1) Decompose original and get decomposition info
\par         decomp_affine(orig_cur_mat, &parts); 
\par      
\par       //2) construct 3x3 rotation from quaternion parts.q
\par         parts.q.MakeMatrix(mat);
\par      
\par       //3) construct position row from translation parts.t  
\par         mat.SetRow(3,  parts.t);
\par      
\par        return(mat);
\par      \}
\par      
\par      //GET_RELATIVE_MATRIX: RETURNS RELATIVE
\par      //MATRIX WITHOUT NON_UNIFORM SCALING
\par      Matrix3 Get_Relative_Matrix(INode *node, int t)
\par      \{          
\par      /* Note: This function removes the non-uniform scaling 
\par      from MAX node transformations. before multiplying the 
\par      current node by  the inverse of its parent. The 
\par      removal  must be done on both nodes before the 
\par      multiplication and Inverse are applied. This is especially 
\par      useful for Biped export (which uses non-uniform scaling on 
\par      its body parts.) */
\par      
\par       INode *p_node  =    node->GetParentNode();
\par      
\par       Matrix3      orig_cur_mat;  // for current and parent 
\par       Matrix3     orig_par_mat;  // original matrices 
\par      
\par       Matrix3      cur_mat;       // for current and parent 
\par       Matrix3     par_mat;       // decomposed matrices 
\par                                                                          
\par       //Get transformation matrices
\par       orig_cur_mat   =      node->GetNodeTM(t);
\par       orig_par_mat   =    p_node->GetNodeTM(t); 
\par       
\par      
\par       //Decompose each matrix
\par       cur_mat =  Uniform_Matrix(orig_cur_mat);
\par       par_mat =  Uniform_Matrix(orig_par_mat);
\par      
\par       //then return relative matrix in coordinate space of parent
\par       return(cur_mat * Inverse( par_mat)); 
\par      \}
\par      
\par      //POSSIBLE USAGE
\par      Matrix3 Get_Relative_Matrix(INode *node, int t);
\par      Matrix3 Uniform_Matrix(Matrix3 orig_cur_mat);
\par      Matrix3 relative_mat;
\par      INode *p_node;
\par      TimeValue tm;
\par      
\par      //For all nodes in biped tree:
\par      p_node      =  node->GetParentNode();
\par      if (p_node) relative_matrix  =  Get_Relative_Matrix( node, tm);
\par      Now convert using:
\par      Your_Euler_Angle_Conversion(relative_matrix, &rotx, &roty, &rotz);
\par      
\par      //NOTE:
\par      //TO GET RELATIVE EULER ANGLES, ONE NEEDS TO KNOW YOUR DESIRED 
\par      ORDERING //OF ROTATIONS IN CONVERTING FROM THE RELATIVE MATRIX 
\par      relative_mat TO
\par      //ROTATIONS ABOUT X,Y,Z
\par      
\par      //Its now the case that: 
\par      //uniform_current_matrix = relative_matrix * uniform_parent_matrix
\par      
\par      //That is for:
\par      current_mat      =   Uniform_Matrix(  node->GetNodeTM(tm));
\par      parent_mat       =   Uniform_Matrix(p_node->GetNodeTM(tm));
\par      relative_mat     =   Get_Relative_Matrix( node, tm);
\par      test_current_mat =   relative_mat * parent_mat;
\par      //It is true that current_mat equals test_current_mat
\par      
\par      
\par 
\par 
\par }}